import Flutter
import UIKit
import TPDirect

public class TappayChargePlugin: NSObject, FlutterPlugin {
    var cardPay: CardPay
    var applePay: ApplePay
    var linePay: LinePay
    var easyWallet: EasyWallet
    
    override public init() {
        cardPay = CardPay()
        applePay = ApplePay()
        linePay = LinePay()
        easyWallet = EasyWallet()
    }

    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "tappay_charge", binaryMessenger: registrar.messenger())
        let instance = TappayChargePlugin()
        registrar.addMethodCallDelegate(instance, channel: channel)
        registrar.addApplicationDelegate(instance)
    }
    
    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        switch call.method {
        case "getPlatformVersion":
            result(TPDSetup.version())
            
        case "initTappay":
            initTappay(arguments: call.arguments, onResult: result)
            
        /// Card Pay
        case "validateCard":
            validateCard(arguments: call.arguments, onResult: result)
        case "getCardPrime":
            createCardToken(arguments: call.arguments, onResult: result)
            
        /// Appley Pay
        case "initApplePay":
            initApplePay(arguments: call.arguments, onResult: result)
        case "startApplePay":
            startApplePay(arguments: call.arguments, onResult: result)
        case "showApplePayResult":
            showApplePayResult(arguments: call.arguments, onResult: result)
            
        /// Line Pay
        case "isLinePayAvailable":
            isLinePayAvailable(arguments: call.arguments, onResult: result)
        case "getLinePayPrime":
            getLinePayPrime(arguments: call.arguments, onResult: result)
        case "redirectLinePay":
            redirectLinePay(arguments: call.arguments, onResult: result)
            
        /// Easy Wallet
        case "isEasyWalletAvailable":
            isEasyWalletAvailable(arguments: call.arguments, onResult: result)
        case "getEasyWalletPrime":
            getEasyWalletPrime(arguments: call.arguments, onResult: result)
        case "redirectEasyWallet":
            redirectEasyWallet(arguments: call.arguments, onResult: result)
            
        default:
            result(FlutterMethodNotImplemented)
        }
  }
    
    /// 初始化Tappay
    private func initTappay(arguments: Any?, onResult: @escaping FlutterResult) {
        guard let params = arguments as? [String: Any],
              let appId = params["appId"] as? Int32,
              let appKey = params["appKey"] as? String,
              let isSandbox = params["isSandBox"] as? Bool else {
            
            let errorResult = TappaySdkCommonResult(success: false, message: "Missing required parameters for initTappay method")
            onResult(errorResult.toDictionary())
            return
        }
        
        TPDSetup.setWithAppId(
            appId,
            withAppKey: appKey,
            with: isSandbox ? TPDServerType.sandBox : TPDServerType.production
        )
        
        let successResult = TappaySdkCommonResult(success: true, message: "Tappay init successful")
        onResult(successResult.toDictionary())
    }
}

/// 信用卡Card
extension TappayChargePlugin {
    /// 驗證卡號是否可用
    private func validateCard(arguments: Any?, onResult: @escaping FlutterResult) {
        guard let params = arguments as? [String: Any],
                let cardNumber = params["cardNumber"] as? String,
                let dueMonth = params["dueMonth"] as? String,
                let dueYear = params["dueYear"] as? String,
                let ccv = params["ccv"] as? String else {
            
            onResult(false)
            return
        }
        
        let isAvailable = cardPay.validateCard(cardNumber: cardNumber, dueMonth: dueMonth, dueYear: dueYear, ccv: ccv)
        onResult(isAvailable)
    }
    
    /// 獲取卡的prime
    private func createCardToken(arguments: Any?, onResult: @escaping FlutterResult) {
        guard let params = arguments as? [String: Any],
                let cardNumber = params["cardNumber"] as? String,
                let dueMonth = params["dueMonth"] as? String,
                let dueYear = params["dueYear"] as? String,
                let ccv = params["ccv"] as? String else {
            
            let errorResult = TappaySdkCommonResult(success: false, message: "Missing required parameters for getCardPrime method")
            onResult(errorResult.toDictionary())
            return
        }
        
        cardPay.createCardToken(cardNumber: cardNumber, dueMonth: dueMonth, dueYear: dueYear, ccv: ccv) { result in
            onResult(result.toDictionary())
        }
    }
}

/// Apple Pay
extension TappayChargePlugin {
    /// 初始化ApplePay
    private func initApplePay(arguments: Any?, onResult: @escaping FlutterResult) {
        guard let params = arguments as? [String: Any],
            let merchantId = params["merchantId"] as? String,
            let merchantName = params["merchantName"] as? String else {
        
            let errorResult = TappaySdkCommonResult(success: false, message: "Missing required parameters for initApplePay method")
            onResult(errorResult.toDictionary())
            return
        }
        
        let currencyCode = params["currencyCode"] as? String
        let countryCode = params["countryCode"] as? String
        let supportedCardTypes = params["supportedCardTypes"] as? [String]
        
        applePay.initApplePay(
            merchantId: merchantId,
            merchantName: merchantName,
            currencyCode: currencyCode,
            countryCode: countryCode,
            supportedCardTypes: supportedCardTypes
        ) { result in
            onResult(result.toDictionary())
        }
    }
    
    /// 發起ApplePay
    private func startApplePay(arguments: Any?, onResult: @escaping FlutterResult) {
        guard let params = arguments as? [String: Any],
              let cartItems = params["cartItems"] as? [[String: Any]],
              let isAmountPending = params["isAmountPending"] as? Bool,
              let isShowTotalAmount = params["isShowTotalAmount"] as? Bool else {
        
            let errorResult = TappayPaymentResult(success: false, status: nil, message: "Missing required parameters for startApplePay method", prime: nil)
            onResult(errorResult.toDictionary())
            return
        }
        
        applePay.startApplePay(
            isAmountPending: isAmountPending,
            isShowTotalAmount: isShowTotalAmount,
            cartItems: cartItems
        ) { result in
            onResult(result.toDictionary())
        }
    }
    
    /// 顯示ApplePay支付結果
    private func showApplePayResult(arguments: Any?, onResult: @escaping FlutterResult) {
        guard let params = arguments as? [String: Any],
            let resultValue = params["result"] as? Bool else {
        
            let errorResult = TappaySdkCommonResult(success: false, message: "Missing required parameters for showApplePayResult method")
            onResult(errorResult.toDictionary())
            return
        }
        
        applePay.showApplePayResult(result: resultValue) { result in
            onResult(result.toDictionary())
        }
    }
}


/// Line Pay
extension TappayChargePlugin {
    /// 检测Line Pay是否可用
    private func isLinePayAvailable(arguments: Any?, onResult: @escaping FlutterResult) {
        onResult(TPDLinePay.isLinePayAvailable())
    }
    
    /// 獲取Line Pay Prime
    private func getLinePayPrime(arguments: Any?, onResult: @escaping FlutterResult) {
        guard let params = arguments as? [String: Any],
            let returnUrl = params["returnUrl"] as? String else {
        
            let errorResult = TappayPaymentResult(success: false, status: nil, message: "Missing required parameters for getLinePayPrime method", prime: nil)
            onResult(errorResult.toDictionary())
            return
        }
        
        linePay.getLinePayPrime(returnUrl: returnUrl) { result in
            onResult(result.toDictionary())
        }
    }
    
    /// 跳轉至Line Pay進行支付
    private func redirectLinePay(arguments: Any?, onResult: @escaping FlutterResult) {
        guard let params = arguments as? [String: Any],
            let paymentUrl = params["paymentUrl"] as? String else {
        
            let errorResult = TappayPaymentResult(success: false, status: nil, message: "Missing required parameters for redirectLinePay method", prime: nil)
            onResult(errorResult.toDictionary())
            return
        }
        
        linePay.redirectLinePay(paymentUrl: paymentUrl) { result in
        
            onResult(result.toDictionary())
        }
    }
}

/// Easy Wallet
extension TappayChargePlugin {
    /// 检测Easy Wallet是否可用
    private func isEasyWalletAvailable(arguments: Any?, onResult: @escaping FlutterResult) {
        onResult(TPDEasyWallet.isEasyWalletAvailable())
    }
    
    /// 獲取Easy Wallet Prime
    private func getEasyWalletPrime(arguments: Any?, onResult: @escaping FlutterResult) {
        guard let params = arguments as? [String: Any],
            let returnUrl = params["returnUrl"] as? String else {
        
            let errorResult = TappayPaymentResult(success: false, status: nil, message: "Missing required parameters for getEasyWalletPrime method", prime: nil)
            onResult(errorResult.toDictionary())
            return
        }
        
        easyWallet.getEasyWalletPrime(returnUrl: returnUrl) { result in
            onResult(result.toDictionary())
        }
    }
    
    /// 跳轉至Easy Wallet進行支付
    private func redirectEasyWallet(arguments: Any?, onResult: @escaping FlutterResult) {
        guard let params = arguments as? [String: Any],
            let paymentUrl = params["paymentUrl"] as? String else {
        
            let errorResult = TappayPaymentResult(success: false, status: nil, message: "Missing required parameters for redirectEasyWallet method", prime: nil)
            onResult(errorResult.toDictionary())
            return
        }
        
        easyWallet.redirectEasyWallet(paymentUrl: paymentUrl) { result in
            onResult(result.toDictionary())
        }
    }
}


/// Application Delegate
extension TappayChargePlugin {
    public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [AnyHashable : Any] = [:]) -> Bool {
        /// 監聽Line Pay支付意外狀況的通知
        TPDLinePay.addExceptionObserver(#selector(tappayLinePayExceptionHandler(notification:)))
        /// 監聽Easy Wallet支付意外狀況的通知
        TPDEasyWallet.addExceptionObserver(#selector(tappayEasyWalletExceptionHandler(notification:)))
        return true
    }
    
    public func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        /// 判斷url是否來自Line Pay
        let tapPayHandled = TPDLinePay.handle(url)
        if (tapPayHandled) {
            return true
        }
        return false
    }
    
    public func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]) -> Void) -> Bool {
        /// 判斷url是否來自Easy Wallet
        if let url = userActivity.webpageURL {
            let easyWalletHandled = TPDEasyWallet.handleUniversalLink(url)
            if (easyWalletHandled) {
                return true
            }
        }
        return true
    }
    
    /// Line Pay支付意外狀況
    @objc func tappayLinePayExceptionHandler(notification: Notification) {
        /// 格式化Line Pay支付錯誤信息
        let result: TPDLinePayResult = TPDLinePay.parseURL(notification)
        
        if (result.status == 0) {   /// 0：成功
            let successResult = TappayPaymentResult(success: true, status: nil, message: "Redirect Line Pay was successful", prime: nil)
            linePay.onLinePayResult?(successResult)
        } else {
            let errorResult = TappayPaymentResult(success: false, status: result.status, message: "Redirect Line Pay was failure", prime: nil)
            linePay.onLinePayResult?(errorResult)
        }

        print("status : \(result.status) , orderNumber : \(result.orderNumber ?? "") , recTradeid : \(result.recTradeId ?? "") , bankTransactionId : \(result.bankTransactionId ?? "")")

    }
    
    /// Easy Pay支付意外狀況
    @objc func tappayEasyWalletExceptionHandler(notification: Notification) {
        /// 格式化Easy Wallet支付錯誤信息
        let result: TPDEasyWalletResult = TPDEasyWallet.parseURL(notification)
        
        if (result.status == 0) {   /// 0：成功
            let successResult = TappayPaymentResult(success: true, status: nil, message: "Redirect Easy Wallet was successful", prime: nil)
            easyWallet.onEasyWalletResult?(successResult)
        } else {
            let errorResult = TappayPaymentResult(success: false, status: result.status, message: "Redirect Easy Wallet was failure", prime: nil)
            easyWallet.onEasyWalletResult?(errorResult)
        }

        print("status : \(result.status) , orderNumber : \(result.orderNumber ?? "") , recTradeid : \(result.recTradeId ?? "") , bankTransactionId : \(result.bankTransactionId ?? "")")

    }
}
